package cn.lucky.thread.deadlock;

/**
 * @Author: jianglingpeng
 * @Date: 2020/9/23
 * @Description:
 *  锁顺序死锁的解决办法
 *      1、固定加锁的顺序 FixedLockingSequence
 *      2、开放调用  OpenCall
 */
public class LockOrderDeadlock {

    public static void main(String[] args) {
        FixedLockingSequence t1 = new FixedLockingSequence();
        new Thread(t1).start();
        new Thread(t1).start();
    }
}


/**
 * 锁顺序死锁的解决办法  --固定加锁顺序
 *  制定一种加锁的顺序,让整个应用的遵循这种规则
 *  使用System.identityHashCode 获取锁对象的HashCode值
 *  比较两把锁的HashCode值大小，然后制定锁顺序规则。
 *  如果hash冲突了，则额外引入一把锁,当hash冲突时，都必须获得这把额外的锁，从而保证一次只有一个线程执行hash冲突时的情况
 */
class FixedLockingSequence implements Runnable{

    private final Object lock1 = new Object();
    private final Object lock2 = new Object();

    private final Object tempLock = new Object();

    //获取lock1的hashCode值
    private int lock1HashCode = System.identityHashCode(lock1);
    //获取lock2的hashCode值
    private int lock2HashCode = System.identityHashCode(lock2);
    @Override
    public void run() {
        A();
        B();
    }

    private void A(){
        if (lock1HashCode > lock2HashCode){
            synchronized (lock1){
                System.out.println(Thread.currentThread().getName() + "的A方法获得了锁1,但是还需获取锁2");
                synchronized (lock2){
                    System.out.println(Thread.currentThread().getName() + "的A方法获得了锁1和锁2");
                }
            }
        }else if (lock1HashCode < lock2HashCode){
            synchronized (lock2){
                System.out.println(Thread.currentThread().getName() + "的A方法获得了锁2,但是还需获取锁1");
                synchronized (lock1){
                    System.out.println(Thread.currentThread().getName() + "的A方法获得了锁2和锁1");
                }
            }
        }else{
            synchronized (tempLock){
                synchronized (lock1){
                    System.out.println(Thread.currentThread().getName() + "的A方法获得了锁1,但是还需获取锁2");
                    synchronized (lock2){
                        System.out.println(Thread.currentThread().getName() + "的A方法获得了锁1和锁2");
                    }
                }
            }
        }

    }

    private void B(){
        if (lock1HashCode > lock2HashCode){
            synchronized (lock1){
                System.out.println(Thread.currentThread().getName() + "的B方法获得了锁1,但是还需获取锁2");
                synchronized (lock2){
                    System.out.println(Thread.currentThread().getName() + "的B方法获得了锁1和锁2");
                }
            }
        }else if (lock1HashCode < lock2HashCode){
            synchronized (lock2){
                System.out.println(Thread.currentThread().getName() + "的B方法获得了锁2,但是还需获取锁1");
                synchronized (lock1){
                    System.out.println(Thread.currentThread().getName() + "的B方法获得了锁2和锁1");
                }
            }
        }else{
            synchronized (tempLock){
                synchronized (lock1){
                    System.out.println(Thread.currentThread().getName() + "的B方法获得了锁1,但是还需获取锁2");
                    synchronized (lock2){
                        System.out.println(Thread.currentThread().getName() + "的B方法获得了锁1和锁2");
                    }
                }
            }
        }
    }
}
